package com.twb.log.aspect;

import com.twb.auth.entity.twbApi.TwbApi;
import com.twb.core.base.entity.BaseLoginUser;
import com.twb.core.cache.redis.RedisUtil;
import com.twb.core.config.TwbConfigProperties;
import com.twb.core.security.TwbSecurityUtil;
import com.twb.log.entity.twbLogOperation.TwbLogOperation;
import com.twb.log.queue.LogQueue;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @author DSY
 * @ClassName TwbLogAspect
 * @Description 日志拦截器
 * @date 2018年11月4日 下午9:04:50
 */
public class TwbLogAspect {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Value("${twb.log.enabled}")
    private Boolean logEnable = true;

    @Autowired
    private LogQueue logQueue;
    @Autowired
    private TwbSecurityUtil twbSecurityUtil;
    @Autowired
    TwbConfigProperties twbConfigProperties;
    @Autowired
    RedisUtil redisUtil;

    private HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        return request;
    }

    /**
     * @param joinPoint
     * @Description 方法调用前触发 记录开始时间
     * @date 2016年11月23日 下午5:10
     */
    public void before(JoinPoint joinPoint) {
        //传入参数
        String params = "";
        // 是否开启性能日志
        if (logEnable) {
            try {
                HttpServletRequest request = this.getRequest();
                request.setAttribute("logEnable", System.currentTimeMillis());

                // 打印请求内容
                logger.info("===============进入日志拦截器[请求内容]===============");
                logger.info("请求地址:" + request.getRequestURL().toString());
                logger.info("请求方式:" + request.getMethod());
                logger.info("请求类方法:" + joinPoint.getSignature());

                Object[] args = joinPoint.getArgs();
                String classType = joinPoint.getTarget().getClass().getName();
                Class<?> clazz = Class.forName(classType);
                String clazzName = clazz.getName();
                // 获取方法名称
                String methodName = joinPoint.getSignature().getName();
                params = TwbLogUtil.getNameAndArgs(this.getClass(), clazzName, methodName, args).toString();
                logger.info("请求类方法参数:" + params);
                request.setAttribute("logParams", params);
            } catch (Exception e) {
                logger.error("before日志异常", e);
            }

        }
    }

    /**
     * @param joinPoint
     * @Description 方法调用后触发 记录结束时间
     * @date 2016年11月23日 下午5:10
     */
    public void after(JoinPoint joinPoint) {
        // 是否开启性能日志
        if (logEnable) {
            HttpServletRequest request = this.getRequest();
            // 去掉后面的后缀 *.tw *.action之类的;
            String requestPath = StringUtils.substringBeforeLast(request.getServletPath(), ".");
            long start = (long) request.getAttribute("logEnable");
            long end = System.currentTimeMillis();
            Long costTime = end - start;
            request.setAttribute("logCostTime", costTime);
            logger.info("性能日志【" + requestPath + "】   耗时【" + costTime + "】");
        }
    }

    /**
     * @param joinPoint
     * @param returnVal
     * @Title afterReturning
     * @Class ArchivesLogAspect.java
     * @Package com.tw.common.aspect
     * @Description 拦截方法存在返回值时
     * @author DSY
     * @date 2017年2月23日 上午10:07:43
     */
    public void afterReturning(JoinPoint joinPoint, Object returnVal) {
        HttpServletRequest request = this.getRequest();
        BaseLoginUser loginUser = twbSecurityUtil.getLoginUser(request);
        Long costTime = (Long) request.getAttribute("logCostTime");
        String params = (String) request.getAttribute("logParams");
        if (loginUser != null) {
            String servletPath = request.getServletPath();

            // 去掉后面的后缀 *.tw *.action之类的
            servletPath = StringUtils.substringBeforeLast(servletPath, ".");
            String key = twbConfigProperties.getLoginApiRedisKey(loginUser.getToken());
            TwbApi twbApi = (TwbApi) redisUtil.getRedisTemplate().opsForHash().get(key, servletPath);

            if (twbApi == null) {
                /*twbApi = new TwbApi();
                twbApi.setUrl(servletPath);*/
            	return;
            }

            TwbLogOperation log = TwbLogUtil.log(twbApi, null, logEnable, loginUser, params, costTime);
            if (null != log) {
                logQueue.add(log);
            }
        }
    }

    /**
     * @param joinPoint
     * @param ex
     * @Title afterThrowing
     * @Class ArchivesLogAspect.java
     * @Package com.tw.common.aspect
     * @Description 拦截方法发生异常时
     * @author DSY
     * @date 2017年2月23日 上午10:07:19
     */
    public void afterThrowing(JoinPoint joinPoint, Exception ex) {
        HttpServletRequest request = this.getRequest();
        BaseLoginUser loginUser = twbSecurityUtil.getLoginUser(request);
        Long costTime = (Long) request.getAttribute("logCostTime");
        String params = (String) request.getAttribute("logParams");
        if (loginUser != null) {
            String servletPath = request.getServletPath();
            // 去掉后面的后缀 *.tw *.action之类的
            servletPath = StringUtils.substringBeforeLast(servletPath, ".");
            String key = twbConfigProperties.getLoginApiRedisKey(loginUser.getToken());
            TwbApi twbApi = (TwbApi) redisUtil.getRedisTemplate().opsForHash().get(key, servletPath);

            if (twbApi == null) {
                /*twbApi = new TwbApi();
                twbApi.setUrl(servletPath);*/
            	return;
            }

            TwbLogOperation log = TwbLogUtil.log(twbApi, null, logEnable, loginUser, params, costTime);
            if (null != log) {
                logQueue.add(log);
            }
        }
    }
}
